home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** Program: Kibitz
- ** File: doevent.c
- ** Written by: Eric Soldan
- **
- ** Copyright © 1990-1991 Apple Computer, Inc.
- ** All rights reserved.
- */
-
-
-
- /*****************************************************************************/
-
-
-
- #include "Kibitz.h" /* Get the Kibitz includes/typedefs, etc. */
- #include "KibitzCommon.h" /* Get the stuff in common with rez. */
- #include "Kibitz.protos" /* Get the prototypes for Kibitz. */
-
- #ifndef __DESK__
- #include <Desk.h>
- #endif
-
- #ifndef __DISKINIT__
- #include <DiskInit.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __TEXTEDITCONTROL__
- #include <TextEditControl.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __UTILITIES__
- #include <Utilities.h>
- #endif
-
-
-
- /*****************************************************************************/
-
-
-
- extern Cursor *gCurrentCursor;
-
-
-
- /*****************************************************************************/
- /*****************************************************************************/
-
-
-
- /* Do the right thing for an event. Determine what kind of event it is, and
- ** call the appropriate routines.
- */
-
- #pragma segment Main
- void DoEvent(EventRecord *event)
- {
- short part, err;
- WindowPtr window;
- char key;
- Point aPoint;
- FileRecHndl frHndl;
- ControlHandle ctl;
- long tick;
- Rect boardRct;
-
- switch(event->what) {
-
- case mouseDown:
- gCurrentCursor = nil;
- /* No shortcuts when we recalculate the cursor region. */
-
- part = FindWindow(event->where, &window);
- if (part != inContent) DoSetCursor(&qd.arrow);
-
- switch(part) {
-
- case inContent:
- if (window != FrontWindow()) {
- SelectWindow(window);
- if (IsAppWindow(window)) {
- DoUpdate(window);
- boardRct = GlobalBoardRect(window);
- if (PtInRect(event->where, &boardRct))
- DoEvent(event);
- }
- /* Do first click if over board. */
- } else
- DoContentClick(window, event);
- break;
-
- case inDrag:
- DragWindow(window, event->where, &qd.screenBits.bounds);
- break; /* Pass screenBits.bounds to
- ** get all gDevices. */
-
- case inGoAway:
- if (TrackGoAway(window, event->where)) {
- CloseOneWindow(window, iClose);
- }
- break;
-
- case inGrow:
- break;
-
- case inMenuBar: /* Process mouse menu command (if any). */
- AdjustMenus();
- DoMenuCommand(MenuSelect(event->where));
- break;
-
- case inSysWindow: /* Let the system handle the mouseDown. */
- SystemClick(event, window);
- break;
-
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(window, event->where, part))
- ZoomToWindowDevice(window, 0, 0, part, true);
- break;
-
- }
- break;
-
- case activateEvt:
- gCurrentCursor = nil;
- /* No shortcuts when we recalculate the cursor region. */
-
- DoActivate((WindowPtr)event->message,
- (event->modifiers & activeFlag));
- break;
-
- case autoKey:
- case keyDown: /* Check for menukey equivalents. */
- key = event->message & charCodeMask;
- if (event->modifiers & cmdKey) { /* Command key down. */
- if (event->what == keyDown) {
- AdjustMenus();
- /* Enable/disable/check menu items properly. */
- DoMenuCommand(MenuKey(key));
- }
- }
- else {
- if (!IsAppWindow(window = FrontWindow())) break;
- frHndl = (FileRecHndl)GetWRefCon(window);
- if (key == 0x03) {
- ctl = (*frHndl)->doc.sendMessage;
- if (!(*ctl)->contrlHilite) {
- HiliteControl(ctl, 1);
- tick = TickCount();
- while (TickCount() < tick + 10);
- HiliteControl(ctl, 0);
- SendMssg(frHndl, kTextMssg);
- }
- }
- else {
- if (CTEKey(event)) {
- AdjustMenus(); /* Avoid unnecessary DoCursor() and speed */
- return; /* up TextEdit entry. */
- }
- }
- }
- break;
-
- case diskEvt:
- gCurrentCursor = nil;
- /* No shortcuts when we recalculate the cursor region. */
-
- if (HiWord(event->message) != noErr) {
- SetPt(&aPoint, kDILeft, kDITop);
- err = DIBadMount(aPoint, event->message);
- }
- break; /* It is not a bad idea to at least call DIBadMount
- ** in response to a diskEvt, so that the user can
- ** format a floppy.
- */
- case kHighLevelEvent:
- gCurrentCursor = nil;
- /* No shortcuts when we recalculate the cursor region. */
-
- DoHighLevelEvent(event);
- break;
-
- case kOSEvent:
- gCurrentCursor = nil;
- /* No shortcuts when we recalculate the cursor region. */
-
- switch ((event->message >> 24) & 0x0FF) {
- /* Must logical and with 0x0FF to get only low byte. */
- /* High byte of message. */
-
- case kMouseMovedMessage:
- break;
-
- case kSuspendResumeMessage:
- /* Suspend/resume is also an activate/deactivate. */
- gInBackground = !(event->message & kResumeMask);
- DoActivate(FrontWindow(), !gInBackground);
- break;
- }
- break;
-
- case updateEvt:
- DoUpdate((WindowPtr)event->message);
- break;
-
- }
-
- DoCursor(false, 0);
- AdjustMenus();
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This is called when a window is activated or deactivated. */
-
- #pragma segment Main
- void DoActivate(WindowPtr window, Boolean becomingActive)
- {
- FileRecHndl frHndl;
- short hilite;
- ControlHandle ctl;
-
- NotifyCancel();
-
- if (IsAppWindow(window)) {
-
- frHndl = (FileRecHndl)GetWRefCon(window);
-
- SetPort(window);
- SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
-
- hilite = 0;
- if (!becomingActive) hilite = 255;
-
- HiliteControl((*frHndl)->doc.gameSlider, hilite);
- HiliteControl((*frHndl)->doc.resign, hilite);
- HiliteControl((*frHndl)->doc.draw, hilite);
-
- if (!(*frHndl)->doc.twoPlayer) hilite = 255;
-
- HiliteControl(ctl = (*frHndl)->doc.sendMessage, hilite);
- OutlineControl(ctl);
- HiliteControl((*frHndl)->doc.beepOnMove, hilite);
- HiliteControl((*frHndl)->doc.beepOnMssg, hilite);
-
- if (!SoundInputAvaliable()) hilite = 255;
- HiliteControl((*frHndl)->doc.record, hilite);
- if (!(*frHndl)->doc.sound) hilite = 255;
- HiliteControl((*frHndl)->doc.sendSnd, hilite);
-
- if ((*frHndl)->doc.arrangeBoard) becomingActive = false;
- CTEWindActivate(window, becomingActive);
-
- DoDrawControls(window, true);
- SetOrigin(0, 0);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This is called when an update event is received for a window. It calls
- ** ImageDocument to draw the contents of an application window. As an
- ** effeciency measure that does not have to be followed, it calls the drawing
- ** routine only if the visRgn is non-empty. This will handle situations where
- ** calculations for drawing or drawing itself is very time-consuming.
- */
-
- #pragma segment Main
- void DoUpdate(WindowPtr window)
- {
- if (IsAppWindow(window)) {
- BeginUpdate(window); /* This sets up the visRgn. */
- if (!EmptyRgn(window->visRgn)) { /* Draw if updating needs doing. */
- SetPort(window);
- ImageDocument((FileRecHndl)GetWRefCon(window), false);
- }
- EndUpdate(window);
- }
- }
-
-
-
- /*****************************************************************************/
-
-
-
- /* This is called when a mouse-down event occurs in the content of a window.
- ** Other applications might want to call FindControl, TEClick, etc., to
- ** further process the click.
- */
-
- #pragma segment Main
- void DoContentClick(WindowPtr window, EventRecord *event)
- {
- Boolean invertBoard;
- short fromRow, fromCol, toRow, toCol, i, myColor;
- short fromSq, toSq, promotion, piece, item;
- short numLegalMoves, part, twoPlayer;
- OSErr err;
- long moveAmount, ref;
- Point clickLoc, releaseLoc;
- Rect boardRect, squareRect;
- RgnHandle dragRgn;
- FileRecHndl frHndl;
- MoveListHndl legalMoves;
- DialogPtr promoteDialog;
- short itemType, ctlNum;
- Handle itemHndl;
- Rect itemRect;
- ControlHandle ctlHit;
-
- if (!IsAppWindow(window)) return;
-
- frHndl = (FileRecHndl)GetWRefCon(window);
- SetPort(window);
- SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
-
- twoPlayer = (*frHndl)->doc.twoPlayer;
-
- clickLoc = event->where;
- GlobalToLocal(&clickLoc);
-
- if (CTEClick(event)) {
- SetOrigin(0, 0);
- return;
- }
- /* If TextEdit control handled the click, we are done. */
-
- if (part = FindControl(clickLoc, window, &ctlHit)) {
- ctlNum = ref = GetCRefCon(ctlHit);
- if ((ref) && (ref < 10)) {
- if (TrackControl(ctlHit, clickLoc, nil)) {
- switch (ctlNum) {
- case 1:
- SendMssg(frHndl, kTextMssg);
- break;
- case 2:
- case 3:
- SetCtlValue(ctlHit, GetCtlValue(ctlHit) ^ 1);
- break;
- case 4:
- case 5:
- SetCtlValue(ctlHit, 1);
- SetCtlValue((*frHndl)->doc.wbStart[5 - ctlNum], 0);
- (*frHndl)->doc.startColor = ctlNum - 4;
- break;
- case 6:
- EndTheGame(frHndl, kWhiteResigns + (*frHndl)->doc.myColor);
- UpdateGameStatus(frHndl);
- if (twoPlayer) {
- SendGame(frHndl, kIsMove);
- /* Show the dialog at the other end. */
- SendGame(frHndl, kResync);
- /* Make sure that simultaneous hits on the
- ** resign button are taken care of. */
- }
- break;
- case 7:
- i = ((*frHndl)->doc.drawBtnState ^ 0x02);
- if (!twoPlayer) i = 0x06;
- if (i >= 0x06) EndTheGame(frHndl, kDrawGame);
- DrawButtonTitle(frHndl, i);
- if (twoPlayer) {
- SendGame(frHndl, kIsMove);
- /* Show the dialog at the other end. */
- SendGame(frHndl, kResync);
- /* Make sure that simultaneous hits on the
- ** draw button are taken care of. */
- }
- break;
- case 8:
- err = RecordSound(frHndl);
- if ((err) && (err != userCanceledErr)) Alert(rErrorAlert, nil);
- break;
- case 9:
- SendMssg(frHndl, kSoundMssg);
- break;
- }
- }
- }
- SetOrigin(0, 0);
-
- if (ctlHit == (*frHndl)->doc.gameSlider)
- TrackControl(ctlHit, clickLoc, nil);
-
- return;
- }
-
- if ((*frHndl)->fileState.readOnly) {
- SetOrigin(0, 0);
- return;
- } /* Don't allow changes if read-only. */
-
- if ((*frHndl)->doc.arrangeBoard) {
- DoArrangeBoard(frHndl, clickLoc);
- return;
- }
-
- SetOrigin(0, 0);
-
- invertBoard = (*frHndl)->doc.invertBoard;
-
- boardRect = BoardRect();
- if (!PtInRect(clickLoc, &boardRect)) return;
-
- fromRow = (clickLoc.v - kBoardVOffset) / kBoardSqSize;
- fromCol = (clickLoc.h - kBoardHOffset) / kBoardSqSize;
-
- squareRect.top = kBoardVOffset + fromRow * kBoardSqSize;
- squareRect.left = kBoardHOffset + fromCol * kBoardSqSize;
- squareRect.bottom = squareRect.top + kBoardSqSize + 2;
- squareRect.right = squareRect.left + kBoardSqSize + 2;
-
- if (invertBoard) {
- fromRow = 7 - fromRow;
- fromCol = 7 - fromCol;
- }
- fromSq = START_IBNDS + 10 * fromRow + fromCol;
-
- if (GameStatus(frHndl) != kGameContinues) return;
- /* Game over, so no moves. */
-
- if ((*frHndl)->doc.resync != kIsMove) return;
- /* Don't allow moves until we are resynced. */
-
- numLegalMoves = (*frHndl)->doc.numLegalMoves;
- legalMoves = (*frHndl)->doc.legalMoves;
-
- for (i = 0; i < numLegalMoves; ++i)
- if ((**legalMoves)[i].moveFrom == fromSq) break;
-
- if (i == numLegalMoves) return;
- /* Clicked on a empty square or on a piece that can't move. */
-
- myColor = (*frHndl)->doc.myColor;
- if (twoPlayer)
- if (WhosMove(frHndl) != myColor) return;
- /* It's the other player's turn. */
-
- if ((myColor == WHITE) && ((*frHndl)->doc.compMovesWhite)) return;
- if ((myColor == BLACK) && ((*frHndl)->doc.compMovesBlack)) return;
- /* Computer is moving this color, so ignore click. */
-
- dragRgn = NewRgn();
- RectRgn(dragRgn, &squareRect);
- moveAmount = DragGrayRgn(dragRgn, clickLoc, &boardRect, &boardRect,
- noConstraint, nil);
- DisposeRgn(dragRgn);
-
- if (moveAmount == 0x80008000L) return;
-
- releaseLoc.h = clickLoc.h + (moveAmount & 0xFFFF);
- moveAmount = moveAmount >> 16;
- releaseLoc.v = clickLoc.v + (moveAmount & 0xFFFF);
-
- toRow = (releaseLoc.v - kBoardVOffset) / kBoardSqSize;
- toCol = (releaseLoc.h - kBoardHOffset) / kBoardSqSize;
- if (invertBoard) {
- toRow = 7 - toRow;
- toCol = 7 - toCol;
- }
- toSq = START_IBNDS + 10 * toRow + toCol;
-
- for (i = 0; i < numLegalMoves; ++i)
- if (
- ((**legalMoves)[i].moveFrom == fromSq) &&
- ((**legalMoves)[i].moveTo == toSq)
- ) break;
-
- if (i == numLegalMoves) return; /* Tried an illegal move. */
-
- promotion = QUEEN; /* If there is a promotion, assume queen. */
-
- if ((toRow == 0) || (toRow == 7)) { /* Possible pawn promotion... */
-
- piece = (*frHndl)->doc.theBoard[fromSq];
- if (piece < 0) piece = -piece;
-
- if (piece == PAWN) { /* It is a pawn promotion... */
- promoteDialog = GetCenteredDialog(rPawnPromotion, nil, nil, (WindowPtr)-1L);
-
- if (promoteDialog) {
- OutlineDialogItem(promoteDialog, 1);
- DoSetCursor(&qd.arrow);
-
- for (item = QUEEN;;) {
- if (promotion != item) {
- GetDItem(promoteDialog, promotion + 1, &itemType, &itemHndl, &itemRect);
- SetCtlValue((ControlHandle)itemHndl, false);
- }
-
- GetDItem(promoteDialog, item + 1, &itemType, &itemHndl, &itemRect);
- SetCtlValue((ControlHandle)itemHndl, true);
- promotion = item;
-
- ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
- if (item == 1) break;
- --item;
- }
- DisposDialog(promoteDialog);
- }
- SetPort(window);
- }
- }
-
- UpdateTime(frHndl, true);
- MakeMove(frHndl, fromSq, toSq, promotion, true);
- ImageDocument(frHndl, true);
- DrawTime(frHndl);
- AdjustGameSlider(frHndl);
- DrawButtonTitle(frHndl, (*frHndl)->doc.twoPlayer);
- UpdateGameStatus(frHndl);
-
- if (twoPlayer) SendGame(frHndl, kIsMove);
- AlertIfGameOver(frHndl);
- }
-
-
-
- /*****************************************************************************/
-
-
-
- #pragma segment Main
- short AlertIfGameOver(FileRecHndl frHndl)
- {
- short status;
- Str255 gameStatMssg;
-
- if ((status = GameStatus(frHndl)) != kGameContinues) {
- UpdateGameStatus(frHndl);
- GetIndString(gameStatMssg, rGameStat, status);
- ParamText(gameStatMssg, nil, nil, nil);
- DoSetCursor(&qd.arrow);
- CenteredAlert(rGameStat, nil);
- }
- return(status);
- }
-
-
-
-